package com.wut.clock.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wut.clock.common.constant.SysUserStatus;
import com.wut.clock.dto.admin.ShiroSysUser;
import com.wut.clock.entity.SysMenu;
import com.wut.clock.entity.SysRole;
import com.wut.clock.entity.SysUser;
import com.wut.clock.mapper.SysMenuMapper;
import com.wut.clock.mapper.SysRoleMapper;
import com.wut.clock.mapper.SysUserMapper;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @program
 * @description
 * @Auther yuwei
 * @Date Created in 2021/9/20 15:26
 */
public class MyRealm extends AuthorizingRealm {

    @Resource
    private SysRoleMapper roleMapper;

    @Resource
    private SysMenuMapper menuMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 权限信息对象info,用来存放查出的用户的所有的角色（role）及权限（permission）
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        ShiroSysUser user = (ShiroSysUser)principalCollection.getPrimaryPrincipal();
        //查出用户对应的角色
        SysRole role = roleMapper.getRoleByUserId(user.getUserId());
        //查出用户对应的资源
        List<SysMenu> menuList = menuMapper.listMenusByUserId(user.getUserId());
        //添加角色到授权信息中
        info.addRole(role.getName());
        if (!CollectionUtils.isEmpty(menuList)) {
            Set<String> permissionSet = new HashSet<>();
            for (SysMenu menu : menuList) {
                if (!StringUtils.isEmpty(menu.getPerms())) {
                    permissionSet.add(menu.getPerms());
                }
            }
            info.setStringPermissions(permissionSet);
        }
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String)authenticationToken.getPrincipal();
        SysUser sysUser = sysUserMapper.selectOne(new QueryWrapper<SysUser>().eq("username",username));
        ShiroSysUser cacheUser = sysUserMapper.getRedisCacheSysUserByUsername(username);
        if (sysUser == null){
            throw new UnknownAccountException("账号不存在！");
        }
        if (SysUserStatus.NOT_AVAILABLE.getCode().equals(sysUser.getStatus())){
            throw new LockedAccountException("帐号已被锁定，禁止登录！");
        }

        cacheUser.setUserInfo(sysUser);
        //查出角色和权限
        SysRole role = roleMapper.getRoleByUserId(sysUser.getId());
        List<SysMenu> menus = menuMapper.listMenusByUserId(sysUser.getId());
        Set<String> permissions = new HashSet<>();
        if (!CollectionUtils.isEmpty(menus)) {
            for (SysMenu menu : menus) {
                if (!StringUtils.isEmpty(menu.getPerms())) {
                    permissions.add(menu.getPerms());
                }
            }
        }
        cacheUser.setRole(role);
        cacheUser.setPermissions(permissions);

        return new SimpleAuthenticationInfo(cacheUser,sysUser.getPassword(),getName());
    }

    /**
     * 清除当前用户权限缓存
     * 使用方法：在需要清除用户权限的地方注入 ShiroRealm,
     * 然后调用其 clearCache方法。
     */
    public void clearCache() {
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);
    }
}
